#ifndef LiNE_H
#define LiNE_H

#include "Vertex.h"

namespace Y{

struct Line{
	
	Line () {}
	
	Line ( const Vertex3f& p0, const Vertex3f& p1 ):
		vertical(false),
		horizontal(false),
		m(0.0f)
	{
		p[0] = p0;
		p[1] = p1;
		if ( p[0] != p[1] ){
		
			if ( fabsf(p[1].x() - p[0].x()) < 0.00001){ vertical = true; }
			else if ( fabsf(p[1].y() - p[0].y()) < 0.00001 ){ horizontal = true;b = p[0].y(); }
			else{
				m = ( ( p[1].y() - p[0].y() ) / ( p[1].x() - p[0].x() ) );
				b = p[0].y() - (m * p[0].x());
			}
			
		}
		else{

		}
	}
	
	void operator() ( const Vertex3f& p0, const Vertex3f& p1 ){
		p[0] = p0;
		p[1] = p1;
		if ( p[0] != p[1] ){
		
			if ( fabsf(p[1].x() - p[0].x()) < 0.00001){ horizontal = false;vertical = true; }
			else if ( fabsf(p[1].y() - p[0].y()) < 0.00001 ){ vertical = false;horizontal = true;m=0;b = p[0].y(); }
			else{
				vertical = false;
				horizontal = false;
				m = ( ( p[1].y() - p[0].y() ) / ( p[1].x() - p[0].x() ) );
				b = p[0].y() - (m * p[0].x());
			}
			
		}
		else{

		}
	}
	
	float m;
	float b;
	Vertex3f p[2];
	bool vertical;
	bool horizontal;
	
	float y (float x) const{ return (x * m + b); }
	float compare ( const Vertex3f& v ) const{	if ( ! horizontal && ! vertical )	{ return (v.y() - m * v.x() - b); }
												else if ( vertical )				{ return (v.x() - p[0].x()); }
												else if ( horizontal )				{ return (v.y() - p[0].y()); }
												else								{ std::cout <<"\n" << "bad compare";exit(13); }
											 }
	
	static Vertex3f intersection (const Line& l1, const Line& l2){
		const float& x1 = l1.p[0].x();
		const float& y1 = l1.p[0].y();
		
		const float& x2 = l1.p[1].x();
		const float& y2 = l1.p[1].y();
		
		const float& x3 = l2.p[0].x();
		const float& y3 = l2.p[0].y();
		
		const float& x4 = l2.p[1].x();
		const float& y4 = l2.p[1].y();
		
		float rx = ((x1 * y2 - y1 * x2) * (x3 - x4) - (x1 - x2) * (x3 * y4 - y3 * x4)) / ((x1 - x2) * (y3 - y4) - (y1 - y2) * (x3 - x4));
		float ry = ((x1 * y2 - y1 * x2) * (y3 - y4) - (y1 - y2) * (x3 * y4 - y3 * x4)) / ((x1 - x2) * (y3 - y4) - (y1 - y2) * (x3 - x4));
		
		return Vertex3f( rx,ry,0.0 );
	}
	
	static Vertex3f intersection (const Vertex3f& v1, const Vertex3f& v2, const Line& l2){
		const float& x1 = v1.x();
		const float& y1 = v1.y();
		
		const float& x2 = v2.x();
		const float& y2 = v2.y();
		
		const float& x3 = l2.p[0].x();
		const float& y3 = l2.p[0].y();
		
		const float& x4 = l2.p[1].x();
		const float& y4 = l2.p[1].y();
		
		
		float rx = ((x1 * y2 - y1 * x2) * (x3 - x4) - (x1 - x2) * (x3 * y4 - y3 * x4)) / ((x1 - x2) * (y3 - y4) - (y1 - y2) * (x3 - x4));
		float ry = ((x1 * y2 - y1 * x2) * (y3 - y4) - (y1 - y2) * (x3 * y4 - y3 * x4)) / ((x1 - x2) * (y3 - y4) - (y1 - y2) * (x3 - x4));
		
		Vertex3f res( rx,ry,0.0 );
		
		return res;
	}
	
	bool contains (const Vertex3f& v){
		if ( ! vertical ){
			float ty = y( v.x() );
			bool b = ( ty == v.y() && ( (v.x() <= p[0].x() && v.x() >= p[1].x()) || (v.x() >= p[0].x() && v.x() <= p[1].x()) ) );
			return b;
		}
		else{
			return ( v.x() == p[0].x() && ( (v.y() <= p[0].y() && v.y() >= p[1].y()) || (v.y() >= p[0].y() && v.y() <= p[1].y()) ) );
		}
	}
	
};

}
#endif